package io.xjar.gui;

import io.xjar.XCryptos;

import javax.swing.*;
import javax.swing.border.TitledBorder;
import javax.swing.filechooser.FileNameExtensionFilter;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

/**
 * XJar图形界面应用程序
 * 用于选择基座项目jar包设置密码、选择插件目录，自动识别所有插件jar，并支持各个模块单独设置密码
 */
public class XJarGUI extends JFrame {
    private JTextField baseJarField;
    private JPasswordField basePasswordField;
    private JTextField pluginDirField;
    private JTextField outputDirField;
    private JPanel pluginPanel;
    private List<PluginEntry> pluginEntries;
    private JButton addButton;
    private JButton removeButton;
    private JButton encryptButton;
    private JTextArea logArea;
    private JButton baseJarButton;
    private JButton pluginDirButton;
    private JButton outputDirButton;

    public XJarGUI() {
        pluginEntries = new ArrayList<>();
        initializeComponents();
        setupLayout();
        setupEventHandlers();
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setTitle("XJar Plus 加密工具");
        setSize(800, 700);
        setLocationRelativeTo(null);
    }

    private void initializeComponents() {
        // 基座项目组件
        baseJarField = new JTextField(30);
        basePasswordField = new JPasswordField(20);
        baseJarButton = new JButton("浏览...");
        
        // 插件目录组件
        pluginDirField = new JTextField(30);
        pluginDirButton = new JButton("浏览...");
        
        // 输出目录组件
        outputDirField = new JTextField(30);
        outputDirButton = new JButton("浏览...");
        
        // 插件面板
        pluginPanel = new JPanel();
        pluginPanel.setLayout(new BoxLayout(pluginPanel, BoxLayout.Y_AXIS));
        pluginPanel.setBorder(new TitledBorder("插件列表"));
        
        // 按钮
        addButton = new JButton("添加插件");
        removeButton = new JButton("删除选中");
        encryptButton = new JButton("开始加密");
        
        // 日志区域
        logArea = new JTextArea(10, 50);
        logArea.setEditable(false);
        JScrollPane logScrollPane = new JScrollPane(logArea);
    }

    private void setupLayout() {
        setLayout(new BorderLayout());
        
        // 顶部面板
        JPanel topPanel = new JPanel(new GridBagLayout());
        topPanel.setBorder(new TitledBorder("配置"));
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.insets = new Insets(5, 5, 5, 5);
        gbc.anchor = GridBagConstraints.WEST;
        
        // 基座项目行
        gbc.gridx = 0; gbc.gridy = 0;
        topPanel.add(new JLabel("基座项目JAR:"), gbc);
        gbc.gridx = 1; gbc.weightx = 1.0; gbc.fill = GridBagConstraints.HORIZONTAL;
        topPanel.add(baseJarField, gbc);
        gbc.gridx = 2; gbc.weightx = 0; gbc.fill = GridBagConstraints.NONE;
        topPanel.add(baseJarButton, gbc);
        
        gbc.gridx = 0; gbc.gridy = 1;
        topPanel.add(new JLabel("基座项目密码:"), gbc);
        gbc.gridx = 1; gbc.fill = GridBagConstraints.HORIZONTAL;
        topPanel.add(basePasswordField, gbc);
        
        // 插件目录行
        gbc.gridx = 0; gbc.gridy = 2;
        topPanel.add(new JLabel("插件目录:"), gbc);
        gbc.gridx = 1; gbc.fill = GridBagConstraints.HORIZONTAL;
        topPanel.add(pluginDirField, gbc);
        gbc.gridx = 2; gbc.fill = GridBagConstraints.NONE;
        topPanel.add(pluginDirButton, gbc);
        
        // 输出目录行
        gbc.gridx = 0; gbc.gridy = 3;
        topPanel.add(new JLabel("输出目录:"), gbc);
        gbc.gridx = 1; gbc.fill = GridBagConstraints.HORIZONTAL;
        topPanel.add(outputDirField, gbc);
        gbc.gridx = 2; gbc.fill = GridBagConstraints.NONE;
        topPanel.add(outputDirButton, gbc);
        
        // 中间面板 - 插件区域
        JPanel centerPanel = new JPanel(new BorderLayout());
        centerPanel.add(new JScrollPane(pluginPanel), BorderLayout.CENTER);
        
        // 插件按钮面板
        JPanel pluginButtonPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
        pluginButtonPanel.add(addButton);
        pluginButtonPanel.add(removeButton);
        centerPanel.add(pluginButtonPanel, BorderLayout.SOUTH);
        
        // 底部面板
        JPanel bottomPanel = new JPanel(new BorderLayout());
        bottomPanel.setBorder(new TitledBorder("操作"));
        bottomPanel.add(encryptButton, BorderLayout.NORTH);
        bottomPanel.add(new JScrollPane(logArea), BorderLayout.CENTER);
        
        add(topPanel, BorderLayout.NORTH);
        add(centerPanel, BorderLayout.CENTER);
        add(bottomPanel, BorderLayout.SOUTH);
    }

    private void setupEventHandlers() {
        // 基座项目JAR选择按钮事件
        baseJarButton.addActionListener(this::selectBaseJar);
        
        // 插件目录选择按钮事件
        pluginDirButton.addActionListener(this::selectPluginDir);
        
        // 输出目录选择按钮事件
        outputDirButton.addActionListener(this::selectOutputDir);
        
        // 其他按钮事件
        addButton.addActionListener(this::addPlugin);
        removeButton.addActionListener(this::removePlugin);
        encryptButton.addActionListener(this::encryptAll);
    }

    private void selectBaseJar(ActionEvent e) {
        JFileChooser fileChooser = new JFileChooser();
        fileChooser.setFileFilter(new FileNameExtensionFilter("JAR 文件", "jar"));
        int result = fileChooser.showOpenDialog(this);
        if (result == JFileChooser.APPROVE_OPTION) {
            File selectedFile = fileChooser.getSelectedFile();
            baseJarField.setText(selectedFile.getAbsolutePath());
        }
    }

    private void selectPluginDir(ActionEvent e) {
        JFileChooser fileChooser = new JFileChooser();
        fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        int result = fileChooser.showOpenDialog(this);
        if (result == JFileChooser.APPROVE_OPTION) {
            File selectedDir = fileChooser.getSelectedFile();
            pluginDirField.setText(selectedDir.getAbsolutePath());
            scanPlugins(selectedDir);
        }
    }

    private void selectOutputDir(ActionEvent e) {
        JFileChooser fileChooser = new JFileChooser();
        fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        int result = fileChooser.showOpenDialog(this);
        if (result == JFileChooser.APPROVE_OPTION) {
            File selectedDir = fileChooser.getSelectedFile();
            outputDirField.setText(selectedDir.getAbsolutePath());
        }
    }

    private void scanPlugins(File pluginDir) {
        // 清除现有插件条目
        pluginEntries.clear();
        pluginPanel.removeAll();
        
        if (pluginDir != null && pluginDir.exists() && pluginDir.isDirectory()) {
            File[] jars = pluginDir.listFiles((dir, name) -> name.toLowerCase().endsWith(".jar"));
            if (jars != null) {
                for (File jar : jars) {
                    addPluginEntry(jar);
                }
            }
        }
        
        pluginPanel.revalidate();
        pluginPanel.repaint();
    }

    private void addPlugin(ActionEvent e) {
        JFileChooser fileChooser = new JFileChooser();
        fileChooser.setFileFilter(new FileNameExtensionFilter("JAR 文件", "jar"));
        fileChooser.setMultiSelectionEnabled(true);
        int result = fileChooser.showOpenDialog(this);
        if (result == JFileChooser.APPROVE_OPTION) {
            File[] selectedFiles = fileChooser.getSelectedFiles();
            for (File file : selectedFiles) {
                addPluginEntry(file);
            }
        }
    }

    private void addPluginEntry(File jarFile) {
        PluginEntry entry = new PluginEntry(jarFile);
        pluginEntries.add(entry);
        pluginPanel.add(entry);
        pluginPanel.revalidate();
        pluginPanel.repaint();
    }

    private void removePlugin(ActionEvent e) {
        Component[] components = pluginPanel.getComponents();
        List<Component> toRemove = new ArrayList<>();
        
        for (Component component : components) {
            if (component instanceof PluginEntry) {
                PluginEntry entry = (PluginEntry) component;
                if (entry.isSelected()) {
                    toRemove.add(component);
                    pluginEntries.remove(entry);
                }
            }
        }
        
        for (Component component : toRemove) {
            pluginPanel.remove(component);
        }
        
        pluginPanel.revalidate();
        pluginPanel.repaint();
    }

    private void encryptAll(ActionEvent e) {
        new SwingWorker<Void, String>() {
            @Override
            protected Void doInBackground() throws Exception {
                publish("开始加密任务...");
                
                String baseJar = baseJarField.getText();
                String basePassword = new String(basePasswordField.getPassword());
                String outputDir = outputDirField.getText();
                
                if (baseJar.isEmpty() || basePassword.isEmpty() || outputDir.isEmpty()) {
                    publish("错误: 请填写所有必填字段");
                    return null;
                }
                
                // 创建输出目录
                Path outputPath = Paths.get(outputDir, "encrypted");
                Path pluginOutputPath = Paths.get(outputDir, "encrypted", "plugins");
                Files.createDirectories(outputPath);
                Files.createDirectories(pluginOutputPath);
                
                publish("加密基座项目: " + baseJar);
                
                try {
                    // 加密基座项目
                    XCryptos.encryption()
                            .from(baseJar)
                            .password(basePassword)
                            .to(outputPath.toString(), "base.jar");
                    
                    publish("基座项目加密完成");
                } catch (Exception ex) {
                    publish("基座项目加密失败: " + ex.getMessage());
                    return null;
                }
                
                // 加密插件
                for (PluginEntry entry : pluginEntries) {
                    if (entry.isSelected()) {
                        String pluginJar = entry.getJarPath();
                        String pluginPassword = new String(entry.getPassword());
                        String pluginName = entry.getPluginName();
                        
                        if (!pluginPassword.isEmpty()) {
                            publish("加密插件: " + pluginName);
                            
                            try {
                                XCryptos.encryption()
                                        .from(pluginJar)
                                        .password(pluginPassword)
                                        .asPlugin()
                                        .to(pluginOutputPath.toString(), pluginName + ".jar");
                                
                                publish("插件 " + pluginName + " 加密完成");
                            } catch (Exception ex) {
                                publish("插件 " + pluginName + " 加密失败: " + ex.getMessage());
                            }
                        }
                    }
                }
                
                publish("所有加密任务完成!");
                return null;
            }
            
            @Override
            protected void process(List<String> chunks) {
                for (String message : chunks) {
                    logArea.append(message + "\n");
                }
                logArea.setCaretPosition(logArea.getDocument().getLength());
            }
        }.execute();
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            try {
                UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
            } catch (Exception e) {
                e.printStackTrace();
            }
            new XJarGUI().setVisible(true);
        });
    }

    /**
     * 插件条目内部类
     */
    private static class PluginEntry extends JPanel {
        private JCheckBox selectBox;
        private JTextField jarPathField;
        private JPasswordField passwordField;
        private File jarFile;

        public PluginEntry(File jarFile) {
            this.jarFile = jarFile;
            initializeComponents();
            setupLayout();
        }

        private void initializeComponents() {
            selectBox = new JCheckBox();
            selectBox.setSelected(true);
            
            jarPathField = new JTextField(20);
            jarPathField.setText(jarFile.getAbsolutePath());
            jarPathField.setEditable(false);
            
            passwordField = new JPasswordField(15);
        }

        private void setupLayout() {
            setLayout(new FlowLayout(FlowLayout.LEFT));
            add(selectBox);
            add(new JLabel("插件:"));
            add(jarPathField);
            add(new JLabel("密码:"));
            add(passwordField);
        }

        public boolean isSelected() {
            return selectBox.isSelected();
        }

        public String getJarPath() {
            return jarFile.getAbsolutePath();
        }

        public char[] getPassword() {
            return passwordField.getPassword();
        }

        public String getPluginName() {
            return jarFile.getName().replace(".jar", "");
        }
    }
}